#include <iostream>
#include <vector>
#include <string>
using namespace std;

//单例模式:当前进程中一个类实例化的对象只能存在一个;
//若想一批数据在当前进程中只存在一份,首先将数据保存到类中,再将保存数据的类设计为单例模式;
//单例类的设计方案: 
//1.构造函数私有化(若构造函数不进行私有化,可以任意创建多个对象)---禁止创建对象
//2.如何创建一个对象---饿汉/懒汉
//饿汉模式---main()函数之前创建对象---创建全局对象
//1. 创建Singleton类,类的私有成员存放数据,构造函数私有化
//2. 创建静态成员对象,类中声明,类外定义,定义时便可保存这批数据
//3. 采用静态成员函数提供此对象的地址方便访问与修改数据
//4. 禁用拷贝构造函数与拷贝赋值函数
//优点:没有线程安全的问题,main()函数之前只有主线程,没有新线程！！
//缺点:
//1.饿汉模式下单例对象保存的数据较多,构造初始化成本较高,会影响程序启动的速度！(迟迟无法进入主线程,无法多线程并发执行)
//2.多个单例类有初始化启动的依赖关系,饿汉无法控制
//eg:假设存在A单例对象与B单例对象,假设要求A对象先初始化,然后B对象再初始化,饿汉无法保证！！
//class Singleton
//{
//public:
//	static Singleton* GetInstance()
//	{
//		return &_sint;
//	}
//
//	//访问私有数据
//	void Print()
//	{
//		cout << "x:" << _x << endl;
//		cout << "y:" << _y << endl;
//		for (auto& e : _vstr)
//		{
//			cout << e << " ";
//		}
//		cout << endl;
//	}
//
//	//修改数据
//	void Modify(const string& str)
//	{
//		_vstr.push_back(str);
//	}
//	//必须禁用拷贝构造与拷贝赋值函数,若不禁用,调用Singleton::GetInstance()获取指针，
//	//对获取到的指针解引用便可直接拷贝构造
//	
//	Singleton(const Singleton& singleton) = delete;
//	Singleton& operator=(const Singleton& singleton) = delete;
//private:
//
//	Singleton(int x = 0, int y = 0, const vector<string>& vstr = {"xxx","yyy"})
//		:_x(x)
//		,_y(y)
//		,_vstr(vstr)
//	{}
//	
//	int _x;
//	int _y;
//	vector<string> _vstr;
//	//类的静态成员变量本质受类域限制的全局变量,不存在对象中,但是可以访问类的私有成员
//	static Singleton _sint;//静态成员变量类中声明
//	//static int _a;
//};
//
//Singleton Singleton::_sint(1, 2, {"陕西","甘肃"});//静态成员变量类外定义,定义时便可初始化

//int main()
//{
//	Singleton::GetInstance()->Print();
//	Singleton::GetInstance()->Modify("辽宁");
//	Singleton::GetInstance()->Print();
//	Singleton* sint = Singleton::GetInstance();
//	
//	return 0;
//}

	
//懒汉模式
class Singleton
{
public:
	//3.哪个线程先调用GetInstance()时,哪个线程创建单例对象&&加锁保护
	static Singleton* GetInstance()
	{
		//第一次调用GetInstance()时,创建单例对象
		//多线程场景下,哪个线程先检测到_psint为空指针,谁去创建单例对象
		//加锁保护
		if (_psint == nullptr)
		{
			_psint = new Singleton(1, 1, {"西安","天水"});
		}
		return _psint;
	}
 
	void Print()
	{
		cout << "x:" << _x << endl;
		cout << "y:" << _y << endl;
		for (auto& e : _vstr)
		{
			cout << e << " ";
		}
		cout << endl;
	}

	void Modify(const string& str)
	{
		_vstr.push_back(str);
	}

	//4.1 释放单例对象(一般期望单例对象在整个进程中是存在的,一般不希望释放）
	static void DelInstance()
	{
		if (_psint)
		{
			delete _psint;
		}
		
	}

	
	Singleton(const Singleton& singleton) = delete;
	Singleton& operator=(const Singleton& singleton) = delete;
private:

	Singleton(int x = 0, int y = 0, const vector<string>& vstr = {"xxx","yyy"})
		:_x(x)
		,_y(y)
		,_vstr(vstr)
	{}
	~Singleton()
	{
		cout << "~Singleton()" << endl;
	}
	
	int _x;
	int _y;
	vector<string> _vstr;
	static Singleton* _psint;//1.定义单例对象的指针变量
    
    //定义全局对象的生命周期释放单例对象(此处可以放在类外)
	class GC
	{
	public:
		~GC()
		{
			Singleton::DelInstance();
		}
	};
	static GC gc;
};

Singleton* Singleton::_psint = nullptr;//2.初始化指针,改进初始化数据成本较高的缺点！！

Singleton::GC Singleton::gc;//4.2 释放单例对象


int main()
{
	Singleton::GetInstance()->Print();
	Singleton::GetInstance()->Modify("辽宁");
	Singleton::GetInstance()->Print();
	Singleton* sint = Singleton::GetInstance();
	return 0;
}
